export var ENVIRONMENT = "production";

const AZURE_DEV_BASE_API_URL = "https://benefactor.azurewebsites.net/api/";
const AZURE_PRODUCTION_BASE_API_URL = "https://benefactorprod.azurewebsites.net/api/";
const LOCAL_BASE_API_URL = "http://localhost:5087/api/";

const API_KEY = "ed99f270-1cab-3ade-822b-81c08e30d57b";
const API_KEY_PARAMETER = "?api_key=" + API_KEY;

let BASE_API_URL = "";

let URLS = {};

const SYSTEM_ID = "PSL";
const JSON_CONTENT_TYPE = "application/json";
const JSON_BODY_HEADERS = {
    "Content-Type": JSON_CONTENT_TYPE
};

export const MIN_BENEFITS_CARD_PRICE = 50;
export const MIN_BENEFIT_VALUE = 10;
export const MIN_REFERER_FEE = 5;

export function setBenefactorApiEnvironment(environment) {
	ENVIRONMENT = environment;
	if (environment === "development") {
		BASE_API_URL = AZURE_DEV_BASE_API_URL;
		setUrls();
	}
	else if (environment === "production") {
		BASE_API_URL = AZURE_PRODUCTION_BASE_API_URL;
		setUrls();
	}
	else if (environment === "local") {
		BASE_API_URL = LOCAL_BASE_API_URL;
		setUrls();
	}
	else {
		console.log("Invalid environment " + environment);
	}
}

setBenefactorApiEnvironment(ENVIRONMENT);

function setUrls() {
	console.log("Setting up urls");
	
	URLS.PRODUCT_API_URL = BASE_API_URL + "product";
	URLS.PRODUCT_REQEUST_URL = URLS.PRODUCT_API_URL + API_KEY_PARAMETER;	
	
	URLS.PRODUCT_TYPE_API_URL = BASE_API_URL + "product_type";
	URLS.PRODUCT_TYPE_REQUEST_URL = URLS.PRODUCT_TYPE_API_URL + API_KEY_PARAMETER;
	
	URLS.BENEFITS_CARD_API_URL = BASE_API_URL + "benefits_card";
	URLS.BENEFITS_CARD_REQEUST_URL = URLS.BENEFITS_CARD_API_URL + API_KEY_PARAMETER;
	URLS.ISSUE_BENEFITS_CARD_THEN_ADD_ORDER_REQEUST_URL = URLS.BENEFITS_CARD_API_URL + "/issuethenaddorder" + API_KEY_PARAMETER;	
	
	URLS.BENEFIT_API_URL = BASE_API_URL + "benefit";
	URLS.BENEFIT_REQEUST_URL = URLS.BENEFIT_API_URL + API_KEY_PARAMETER;	
	
	URLS.ISSUED_BENEFITS_CARD_API_URL = BASE_API_URL + "issued_benefits_card";
	URLS.ISSUED_BENEFITS_CARD_REQUEST_URL = URLS.ISSUED_BENEFITS_CARD_API_URL + API_KEY_PARAMETER;
	
	URLS.VOUCHER_API_URL = BASE_API_URL + "voucher";
	URLS.VOUCHER_REQEUST_URL = URLS.VOUCHER_API_URL + API_KEY_PARAMETER;	
	
	URLS.BENEFITS_CARD_PRODUCT_API_URL = BASE_API_URL + "benefits_card_product";
	URLS.BENEFITS_CARD_PRODUCT_REQEUST_URL = URLS.BENEFITS_CARD_PRODUCT_API_URL + API_KEY_PARAMETER;	
	
	URLS.BENEFITS_CARD_ORDER_API_URL = BASE_API_URL + "benefits_card_order";
	URLS.BENEFITS_CARD_ORDER_REQEUST_URL = URLS.BENEFITS_CARD_ORDER_API_URL + API_KEY_PARAMETER;	
	
	URLS.REFERER_COMMISSION_API_URL = BASE_API_URL + "referer_commission";
	URLS.REFERER_COMMISSION_REQEUST_URL = URLS.REFERER_COMMISSION_API_URL + API_KEY_PARAMETER;	
	
	URLS.REFERER_COMMISSION_WITHDRAWAL_API_URL = BASE_API_URL + "referer_commission_withdrawal";
	URLS.REFERER_COMMISSION_WITHDRAWAL_REQEUST_URL = URLS.REFERER_COMMISSION_WITHDRAWAL_API_URL + API_KEY_PARAMETER;
	
	URLS.VERSION_REQEUST_URL = BASE_API_URL + "version";
}

export function makeRequest(url, method, headers, data) {
    var jsonBody = data === undefined || data === null? null : JSON.stringify(data);

    console.log("The " + method + " request url is:");
    console.log(url);

    if (hasValue(jsonBody)) {
        console.log("The request json body is:");
	    console.log(jsonBody);
    }
	
	var isNonUniEnvironment = typeof(uni) === "undefined" || 
		typeof(uni?.request) === "undefined";
		
	return new Promise((resolve, reject) => {
        if (isNonUniEnvironment) {
            var requestPromise = fetch(url, {
                method: method || "GET",
                headers: headers,
                body: jsonBody
            });

            handleResponse(requestPromise, resolve, reject);

            return;
        }

        data = data || {};
        uni.request({
            url: url,
            method: method || "GET",
            header: headers,
            data: data,
            success: (res) => {
                handleJsonResponse(res.data, resolve, reject);
            },
            fail: (message) => {
                handleJsonResponse(message, "", reject);
            }
        });
    });
}

export function padToDigits(num, numOfDigits = 2) {
    return num.toString().padStart(numOfDigits, '0');
}

export function formatDate(date = new Date()) {
    return [
        date.getFullYear(),
        padToDigits(date.getMonth() + 1),
        padToDigits(date.getDate()),
    ].join('-');
}

export function formatDateTimeToMinutes(date = new Date()) {
    return formatDate(date) + ' ' + [
        padToDigits(date.getHours()),
        padToDigits(date.getMinutes())
    ].join(':');
}

async function handleResponse(requestPromise, resolve, reject) {
    try {
        var response = await requestPromise;
        if (!response.ok) {
            var text = await response.text();
            handleFailResponse(text, "status - " + response.status, reject);
            return;
        }
        var text = await response.text();
        try {
            var json = JSON.parse(text);
            handleJsonResponse(json, resolve, reject);
        } catch(error) {
            handleFailResponse(text, "", reject);
        }
    } catch(error) {
        console.log(error);
        handleFailResponse(error.message, error.cause, reject);
    }
}

function isFailJsonResponse(response) {
    return typeof(response.status) === "number";
}

function handleJsonResponse(jsonResponse, resolve, reject) {
    if (isFailJsonResponse(jsonResponse)) { 
        handleFailJsonResponse(jsonResponse, reject);
        return;
    }

    var error = jsonResponse.error;
    var data = jsonResponse.data;
    if (error.code === 200) {
        resolve(data);
    } else {
        reject(error);
    }
}

function handleFailJsonResponse(jsonResponse, reject) {
    var message = jsonResponse.message || jsonResponse.title;
    var errors = jsonResponse.errors;
    if (hasValue(errors)) {
        for (const key in errors) {
            if (errors.hasOwnProperty(key)) {
                var errorValue = errors[key];
                message += " " + key + ": ";
                if (Array.isArray(errorValue)) {
                    errorValue.forEach(errorItem => {
                        message += errorItem + " ";
                    })
                } else {
                    message += errorValue + "";
                }
            }
        }

        message = message.trim();
    }

    var error = {
        code: jsonResponse.status,
        message,
        user_message: "服务器发生未知错误, 请稍候再试"
    };
    reject(error);
}

function handleFailResponse(message, cause, reject) {
    if (cause === undefined || cause === null || isNaN(cause)) {
        cause = "";
    } else {
        cause = ". " + cause;
    }
    reject({
        code: 500,
        message: "The API service is unaccessible: " + (message || "unknown error") + cause,
        user_message: "后台服务无法访问: " + (message || "未知错误")  + cause
    });
}

export function hasValue(data) {
    return data !== undefined && data !== null;
}

export function addQuery(url, parameterName, parameterValue) {
    if (!hasValue(parameterValue)) {
        return url;
    }
    
    if (parameterValue === true) {
        parameterValue = "true";
    }
    if (parameterValue === false) {
        parameterValue = "false";
    }
    if (url.includes("?"))
        url += "&" ;
    else
        url += "?" ;

    if (Array.isArray(parameterValue)) {
        for (var i = 0; i < parameterValue.length; i++) {
            var value = parameterValue[i];
            url = addQuery(url, parameterName, value);
        }

        return url;
    }

    return url + parameterName + "=" + encodeURI(parameterValue);
}

export function getProductTypes() {
    var url = URLS.PRODUCT_TYPE_REQUEST_URL;
    url = addQuery(url, "system_id", SYSTEM_ID);

    return makeRequest(url, "GET");
}

export function addProduct(merchantId, name, description, productTypeCode, value) {
    let url = URLS.PRODUCT_REQEUST_URL;
    let data = {
        system_id: SYSTEM_ID,
        merchant_id: merchantId,
        name,
        description,
        product_type_code: productTypeCode,
        value
    };

    return makeRequest(url, "POST", JSON_BODY_HEADERS, data);
}

export function updateProduct(
	id, 
	merchantId, 
	name, 
	description, 
	productTypeCode, 
	value) {
    let url = URLS.PRODUCT_REQEUST_URL;
    let data = {
        id,
        system_id: SYSTEM_ID,
        merchant_id: merchantId,
        name,
        description,
        product_type_code: productTypeCode,
        value
    };

    return makeRequest(url, "PUT", JSON_BODY_HEADERS, data);
}

export function deleteProduct(id) {
    let url = URLS.PRODUCT_REQEUST_URL;
    let data = { id };

    return makeRequest(url, "DELETE", JSON_BODY_HEADERS, data);
}

export function getProducts(productId, merchantIds) {
    var url = URLS.PRODUCT_REQEUST_URL;
    url = addQuery(url, "system_id", SYSTEM_ID);
    url = addQuery(url, "merchant_ids", merchantIds);
    url = addQuery(url, "product_id", productId);

    return makeRequest(url, "GET");
}

export function addBenefit(benefitsCardId, productId, count, imageUrl) {
    let url = URLS.BENEFIT_REQEUST_URL;
    let data = {
        system_id: SYSTEM_ID,
        product_id: productId,
        benefits_card_id: benefitsCardId,
        count,
		image_url: imageUrl
    };

    return makeRequest(url, "POST", JSON_BODY_HEADERS, data);
}

export function updateBenefit(id, productId, count, imageUrl) {
    let url = URLS.BENEFIT_REQEUST_URL;
    let data = {
        id, 
        product_id: productId,
        count,
		image_url: imageUrl
    };
	
	console.log("The image url of the benefit is " + imageUrl);

    return makeRequest(url, "PUT", JSON_BODY_HEADERS, data);
}

export function getBenefits(benefitsCardId, benefitId, productId) {
    var url = URLS.BENEFIT_REQEUST_URL;
    url = addQuery(url, "system_id", SYSTEM_ID);
    url = addQuery(url, "benefits_card_id", benefitsCardId);
	url = addQuery(url, "benefit_id", benefitId);
	url = addQuery(url, "product_id", productId);

    return makeRequest(url, "GET");
}

export function deleteBenefit(id) {
    let url = URLS.BENEFIT_REQEUST_URL;
    var data = { id };

    return makeRequest(url, "DELETE", JSON_BODY_HEADERS, data);
}

export function addBenefitsCard(
	name, 
    description, 
    price,
    imageUrl,
    districtId, 
    districtPrefix,
    districtLatitude,
    districtLongitude,
    districtAltitude,
	refererFee,
	merchantProductId) {
    let url = URLS.BENEFITS_CARD_REQEUST_URL;
    let data = {
        system_id: SYSTEM_ID,
        name,
        description,
        price,
        image_url: imageUrl,
        district_id: districtId,
        district_prefix: districtPrefix,
        district_latitude: districtLatitude,
        district_longitude: districtLongitude,
        district_altitude: districtAltitude,
		referer_fee: refererFee,
		merchant_product_id: merchantProductId
    };

    return makeRequest(url, "POST", JSON_BODY_HEADERS, data);
}

export function updateBenefitsCard(
    id,
    name, 
    description, 
    price,
    imageUrl,
    districtId, 
    districtPrefix,
    districtLatitude,
    districtLongitude,
    districtAltitude,
	refererFee,
	merchantProductId) {
    let url = URLS.BENEFITS_CARD_REQEUST_URL;
    let data = {
        system_id: SYSTEM_ID,
        id,
        name,
        description,
        price,
        image_url: imageUrl,
        district_id: districtId,
        district_prefix: districtPrefix,
        district_latitude: districtLatitude,
        district_longitude: districtLongitude,
        district_altitude: districtAltitude,
        district_prefix: districtPrefix,
		referer_fee: refererFee,
		merchant_product_id: merchantProductId
    };

    return makeRequest(url, "PUT", JSON_BODY_HEADERS, data);
}

export function getBenefitsCards(districtIds, benefitsCardId, includeBenefits) {
    var url = URLS.BENEFITS_CARD_REQEUST_URL;
    url = addQuery(url, "system_id", SYSTEM_ID);
    url = addQuery(url, "district_ids", districtIds);
    url = addQuery(url, "benefits_card_id", benefitsCardId);
	url = addQuery(url, "include_benefits", includeBenefits);

    return makeRequest(url, "GET");
}

export function deleteBenefitsCard(id) {
    let url = URLS.BENEFITS_CARD_REQEUST_URL;
    let data = { id };

    return makeRequest(url, "DELETE", JSON_BODY_HEADERS, data);
}

export function issueBenefitsCardThenAddOrder(benefitsCardId, 
	userId, 
	validFrom, 
	validTo, 
	refererAccount,
	refererFee,
	orderNo,
	paidAmount,
	paidTime) {
    let url = URLS.ISSUE_BENEFITS_CARD_THEN_ADD_ORDER_REQEUST_URL;
    let data = {
        system_id: SYSTEM_ID,
        benefits_card_id: benefitsCardId,
        user_id: userId,
        valid_from: validFrom,
        valid_to: validTo,
		referer_account: refererAccount,
		referer_fee: refererFee,
		order_no: orderNo,
		paid_amount: paidAmount,
		paid_time: paidTime
    };

    return makeRequest(url, "POST", JSON_BODY_HEADERS, data);
}

export async function getIssuedBenefitsCards(userId, 
	issuedBenefitsCardId, 
	benefitsCardId,
	includeVouchers) {
    var url = URLS.ISSUED_BENEFITS_CARD_REQUEST_URL;
    url = addQuery(url, "system_id", SYSTEM_ID);
    url = addQuery(url, "user_id", userId);
    url = addQuery(url, "issued_benefits_card_id", issuedBenefitsCardId);
	url = addQuery(url, "benefits_card_id", benefitsCardId);
	url = addQuery(url, "include_vouchers", includeVouchers);

    var issuedBenefitsCards = await makeRequest(url, "GET");
	
	for (let issuedBenefitsCard of issuedBenefitsCards) {
		const voucherValidFrom = issuedBenefitsCard.voucher_valid_from;
		const voucherValidTo = issuedBenefitsCard.voucher_valid_to;
		const issuedBenefitsCardNo = issuedBenefitsCard.card_no;
		const userId = issuedBenefitsCard.user_id;
		
		for (let merchant of issuedBenefitsCard.merchants) {
			for (let benefit of merchant.benefits) {
				for (let voucher of benefit.vouchers) {
					voucher.valid_from = voucherValidFrom;
					voucher.valid_to = voucherValidTo;
					voucher.issued_benefits_card_no = issuedBenefitsCardNo;
					voucher.name = benefit.product.name;
					voucher.merchant_id = merchant.id;
					voucher.user_id = userId;
					voucher.benefit_id = benefit.id;
					voucher.product_id = benefit.product.id;
				}
			}
		}
	}
	
	return issuedBenefitsCards;
}

export function getVouchers(issuedBenefitsCardId, voucherId) {
    var url = URLS.VOUCHER_REQEUST_URL;
    url = addQuery(url, "system_id", SYSTEM_ID);
    url = addQuery(url, "issued_benefits_card_id", issuedBenefitsCardId);
    url = addQuery(url, "voucher_id", voucherId);

    return makeRequest(url, "GET");
}

export function useVoucher(voucherId,
	merchantId,
	productId,
	userId,
	issuedBenefitsCardNo,
	consumeCode) {
    const url = URLS.VOUCHER_REQEUST_URL;
	const data = {
		voucher_id: voucherId,
		system_id: SYSTEM_ID,
		merchant_id: merchantId,
		product_id: productId,
		user_id: userId,
		issued_benefits_card_no: issuedBenefitsCardNo,
		consume_code: consumeCode
	};

    return makeRequest(url, "POST", JSON_BODY_HEADERS, data);
}

export function getBenefitsCardProducts() {
	var url = URLS.BENEFITS_CARD_PRODUCT_REQEUST_URL;
	url = addQuery(url, "system_id", SYSTEM_ID);
	
	return makeRequest(url, "GET");
}

export function getBenefitsCardOrders(benefitsCardId, benefitsCardOrderId, buyerAccount, merchantProductId) {
	var url = URLS.BENEFITS_CARD_ORDER_REQEUST_URL;
	url = addQuery(url, "system_id", SYSTEM_ID);
	url = addQuery(url, "benefits_card_id", benefitsCardId);
	url = addQuery(url, "benefits_card_order_id", benefitsCardOrderId);
	url = addQuery(url, "buyer_account", buyerAccount);
	url = addQuery(url, "merchant_product_id", merchantProductId);
	
	return makeRequest(url, "GET");
}

export function getRefererCommissions(refererAccount) {
	var url = URLS.REFERER_COMMISSION_REQEUST_URL;
	url = addQuery(url, "system_id", SYSTEM_ID);
	url = addQuery(url, "referer_account", refererAccount);
	
	return makeRequest(url, "GET");
}

export function addRefererCommissionWithdrawal(
	refererAccount,
	amount
	) {
	let url = URLS.REFERER_COMMISSION_WITHDRAWAL_REQEUST_URL;
	let data = {
	    system_id: SYSTEM_ID,
		referer_account: refererAccount,
		amount
	};
	
	return makeRequest(url, "POST", JSON_BODY_HEADERS, data);
}

export function getBenefactorVersion() {
	let url = URLS.VERSION_REQEUST_URL;
	return makeRequest(url, "GET");
}

async function testProductTypesAsync() {
    var productTypes = await getProductTypes();
    console.log("Got " + productTypes.length + " product types");
    console.log(productTypes);

    return productTypes;
}

async function addTestProductAsync(productTypeCode) {
    const merchantId = "3"; 
    const productName = "天黑瀑免费洗剪吹三次券";
    const description = "凭券在万象汇商圈天黑瀑理发店免费洗剪吹";
    return await addProduct(merchantId, productName, description, productTypeCode, 100);
}

async function updateTestProductAsync(productTypeCode) {
    const productId = "dXJGYDAKs";
    var products = await getProducts(productId);
    if (products.length === 0) {
        console.log("Cannot find the product with id " + productId);
        return;
    }

    var product = products[0];
    console.log("Got product: ");
    console.log(products[0]);
    const newProductName = "老碗会五折券三张";
    const newProductDescription = "凭券在老碗会消费享五折超值优惠";
    const newValue = 250;
    await updateProduct(productId, product.merchant_id, newProductName, newProductDescription, productTypeCode, newValue);
    console.log("Successfully updated product with id " + productId);
}

async function addTestBenefitsCardAsync() {
    const districtId = "syPHAzmWKHnl";
    const districtPrefix = "ND";
    const name = "诺德商圈尊享权益卡";
    const description = "诺德商圈超值优惠组合";
    const price = 199.99;
    const districtLatitude = 113.903525;
    const districtLongitude = 22.509102;
    const districtAltitude = 0;
    const imageUrl = "https://psladmin.jingmeikeji.cc/api/file/112/008bBX2Dgy1hum8bq1skij30j60pj3zs.jpg";
    
    return await addBenefitsCard(name, description, price, imageUrl, districtId, districtPrefix, districtLatitude, districtLongitude, districtAltitude);
}

async function updateTestBenefitsCardAsync() {
    const districtId = "syPHAzmWKHnl";

    var benefitsCards = await getBenefitsCards([districtId]);

    if (benefitsCards.length === 0) {
        console.log("No benefits card found for district id " + districtId);
        return;
    }

    console.log("Got " + benefitsCards.length + " benefits cards: ");
    console.log(benefitsCards);

    var firstBenefitCard = benefitsCards[0];

    await updateBenefitsCard(
        firstBenefitCard.id, 
        firstBenefitCard.name, 
        firstBenefitCard.description, 
        firstBenefitCard.price + 100,
        firstBenefitCard.image_url,
        districtId, 
        "HL",
        firstBenefitCard.district_latitude, 
        firstBenefitCard.district_longitude, 
        firstBenefitCard.district_altitude + 120,
    );

    console.log("Successfully updated benefits card with id " + firstBenefitCard.id);
}

async function issueTestBenefitsCardAsync() {
    const userId = "18823214892";
    const benefitsCardId = "txzWAMsdm";

    var issuedBenefitsCard = await issueBenefitsCard(
        benefitsCardId, 
        userId,
        "2024-10-31",
        "2028-10-31"
    );

    console.log("Issued benefit card:");
    console.log(issuedBenefitsCard);
}

async function addTestBenefitAsync() {
    let benefitsCardId = "txzWAMsdm";
    let productId = "dXJGYDAKs";

    return await addBenefit(benefitsCardId, productId, 10);
}

async function updateTestBenefitAsync() {
    const benefitsCardId = "txzWAMsdm";
    let benefits = await getBenefits(benefitsCardId, null, null);

    if (benefits.length === 0) {
        console.log("No benefits found for benefits cardid " + districtId);
        return;
    }

    console.log("Got " + benefits.length + " benefits");
    console.log(benefits);

    var benefit = benefits[0];
    await updateBenefit(benefit.id, benefit.product_id, benefit.count + 1);
    console.log("Successfully update benefit with id " + benefit.id);
}

async function addTestBenefitsCardOrderAsync() {
    const benefitsCardId = "jyreeDMuo";
    const userAccount = "18823214892";
    const orderNo = "SH665173036017129652746";
    const orderPrice = 0.01;
    var paidTime = "2024-10-31T15:53:08";

    let issuedBenefitsCard = {
        id: "gDdxVKfTCz",
        card_no: "80000029"
    };

    console.log("Adding benefits card order");

    var benefitsCardOrder = await addBenefitsCardOrder(
        userAccount,
        benefitsCardId,
        null,
        null,
        issuedBenefitsCard.id,
        issuedBenefitsCard.card_no,
        orderNo,
        orderPrice,
        paidTime
    );

    console.log("The benefits card order is:");
    console.log(benefitsCardOrder);
}

async function sanityTests() {
    // Get the product types
    //var productTypes = await testProductTypesAsync();

    // var product = await addTestProductAsync(productTypes[0].code);
    // console.log("Added product with id " + product.id);

    // await updateTestProductAsync(productTypes[1].code);

    // const productId = "vLsXNpseISDKj";
    // await deleteProduct(productId);
    // console.log("Successfully deleted product with id " + productId);

    // var benefitsCard = await addTestBenefitsCardAsync();
    // console.log("Added benefits card with id " + benefitsCard.id);

    // await updateTestBenefitsCardAsync();

    // var benefit = await addTestBenefitAsync();
    // console.log("Added benefit with id " + benefit.id);

    // await updateTestBenefitAsync();

    // await issueTestBenefitsCardAsync();

    // var vouchers = await getVouchers("txzWAMsdm");
    // console.log("Got vouchers:");
    // console.log(vouchers);

    await addTestBenefitsCardOrderAsync();
}

async function runSanityTests() {
    try {
        await sanityTests();
   }
   catch (e) {
       console.log("Error happened:");
       console.log(e);
   }
}

// await runSanityTests();

